# $Id: crypto.py 7557b5d4d82b 2012/12/02 09:07:16 pgurumur $
# Copyright (c) 2009 Prabhu Gurumurthy  <pgurumur@gmail.com>
# 
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

__version__ = "$Revision: 7557b5d4d82b $"
__author__ = "$Author: pgurumur $"

import hashlib

from Crypto.Cipher import AES, Blowfish, DES3

from djanet.lib import stdlib
from djanet.lib.exception import CryptoError

class crypto(object):
   def __init__(self, Key):
      super(crypto, self).__init__()
      self._err = CryptoError()
      self._key = None
      self._crypt = None

      if Key:
         self._key = hashlib.md5(Key).hexdigest()
      else:
         raise CryptoError, "no key defined!"

   def encrypt(self, inputString):
      raise NotImplementedError()

   def decrypt(self, inputString):
      raise NotImplementedError()

class aes(crypto):
   def __init__(self, Key):
      super(aes, self).__init__(Key)
      self._crypt = AES.new(self._key)
      self._eod = hashlib.md5(self._key).hexdigest()

   def encrypt(self, inputString):
      encString = None
      if inputString:
         saltLength = 0
         dataLength = len(inputString) + len(self._eod)
         if dataLength < 16:
            saltLength = 16 - dataLength
         else:
            saltLength = 16 - dataLength % 16

         encString = ''.join([inputString, self._eod, stdlib.GetRandomString(
            saltLength)])
      else:
         raise CryptoError, "no string given to encrypt"

      return self._crypt.encrypt(encString)

   def decrypt(self, inputString):
      retval = None
      if inputString:
         decString = self._crypt.decrypt(inputString)
         retval = decString.split(self._eod)[0]

      return retval

class blowfish(crypto):
   def __init__(self, Key):
      super(blowfish, self).__init__(Key)
      self._strLength = 8
      self._crypt = Blowfish.new(self._key)

   def encrypt(self, inputString):
      retval = None
      if inputString:
         repeat = self._strLength - len(inputString) % 8
         inputString = inputString + " " * repeat
         retval = self._crypt.encrypt(inputString)
         
      return retval

   def decrypt(self, inputString):
      retval = None
      if inputString:
         retval = self._crypt.decrypt(inputString).strip()

      return retval

class tripledes(crypto):
   def __init__(self, Key):
      super(tripledes, self).__init__(Key)
      self._strLength = 8
      self._crypt = DES3.new(self._key[:24])

   def encrypt(self, inputString):
      retval = None
      if inputString:
         repeat = self._strLength - len(inputString) % 8
         inputString = inputString + " " * repeat
         retval = self._crypt.encrypt(inputString)
         
      return retval

   def decrypt(self, inputString):
      retval = None
      if inputString:
         retval = self._crypt.decrypt(inputString).strip()

      return retval
